home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
MPW_TOOL
/
TOOLS
/
TOOLS_WI
/
ICON_8
/
ICONX_FO
/
RDOASGN.C
< prev
next >
Wrap
Text File
|
1990-03-02
|
8KB
|
239 lines
/*
* File: rdoasgn.c
* Contents: doasgn.c
*/
#include "::h:config.h"
#include "::h:rt.h"
#include "rproto.h"
/*
* doasgn - assign value of dp2 to variable dp1.
* Does the work for asgn, swap, rasgn, and rswap.
*/
int doasgn(dp1, dp2)
dptr dp1, dp2;
{
register word i1, i2;
register union block *bp;
register struct b_table *tp;
register uword hn;
int (*putf)();
int ret_code;
union block *hook, **slot;
char sbuf1[MaxCvtLen];
tended[1] = *dp1;
tended[2] = *dp2;
ntended = 2;
assign:
if (!Tvar(tended[1]))
*(dptr)((word *)VarLoc(tended[1]) + Offset(tended[1])) = tended[2];
else switch (Type(tended[1])) {
case T_Tvsubs:
/*
* An assignment is being made to a substring trapped
* variable. The tended descriptors are used as
* follows:
*
* tended[1] - the substring trapped variable
* tended[2] - the value to assign
* tended[3] - the string containing the substring
* tended[4] - the substring
* tended[5] - the result string
*/
/*
* Be sure that the value to be assigned is a string.
*/
ntended = 5;
if (DeRef(tended[2]) == Error) {
ntended = 0;
return Error;
}
if (cvstr(&tended[2], sbuf1) == CvtFail) {
ntended = 0;
RetError(103, tended[2]);
}
/*
* Be sure that the variable in the trapped variable points
* to a string.
*/
tended[3] = BlkLoc(tended[1])->tvsubs.ssvar;
if (DeRef(tended[3]) == Error) {
ntended = 0;
return Error;
}
if (!Qual(tended[3])) {
ntended = 0;
RetError(103, tended[3]);
}
if (strreq(StrLen(tended[3]) + StrLen(tended[2])) == Error)
return Error;
/*
* Get a pointer to the substring trapped-variable block and
* make i1 a C-style index to the character that begins the
* substring.
*/
bp = BlkLoc(tended[1]);
i1 = bp->tvsubs.sspos - 1;
/*
* Make tended[4] a descriptor for the substring.
*/
StrLen(tended[4]) = bp->tvsubs.sslen;
StrLoc(tended[4]) = StrLoc(tended[3]) + i1;
/*
* Make i2 a C-style index to the character after the
* substring. If i2 is greater than the length of the
* substring, it is an error because the string being
* assigned will not fit.
*/
i2 = i1 + StrLen(tended[4]);
if (i2 > StrLen(tended[3])) {
ntended = 0;
RetError(-205, nulldesc);
}
/*
* Form the result string. First, copy the portion of the
* substring string to the left of the substring into the
* string space.
*/
StrLoc(tended[5]) = alcstr(StrLoc(tended[3]), i1);
/*
* Copy the string to be assigned into the string space,
* effectively concatenating it.
*/
alcstr(StrLoc(tended[2]), StrLen(tended[2]));
/*
* Copy the portion of the substring to the right of
* the substring into the string space, completing the
* result.
*/
alcstr(StrLoc(tended[3]) + i2, StrLen(tended[3]) - i2);
/*
* Calculate the length of the new string.
*/
StrLen(tended[5]) = StrLen(tended[3]) - StrLen(tended[4]) +
StrLen(tended[2]);
bp->tvsubs.sslen = StrLen(tended[2]);
tended[1] = bp->tvsubs.ssvar;
tended[2] = tended[5];
/*
* Everything is set up for the actual assignment. Go
* back to the beginning of the routine to do it.
*/
goto assign;
case T_Tvtbl:
/*
*
* The tended descriptors are used as follows:
*
* tended[1] - the table element trapped variable
* tended[2] - the value to be assigned
* tended[3] - subscripting value
*/
/*
* Point bp to the trapped-variable block, point tended[3]
* to the subscripting value, and point tp to the table-
* header block.
*/
ntended = 3;
bp = BlkLoc(tended[1]);
if (bp->tvtbl.title == T_Telem) {
/*
* The trapped-variable block already has been
* converted to a table-element block. Just assign
* to it and return.
*/
bp->telem.tval = tended[2];
ntended = 0;
return Success;
}
tended[3] = bp->tvtbl.tref;
tp = (struct b_table *)bp->tvtbl.clink;
/*
* Get the hash number for the subscripting value and
* locate the chain that contains the element to which
* assignment is to be made.
*/
hn = bp->tvtbl.hashnum;
slot = hchain((union block *)tp, hn);
bp = *slot;
/*
* Traverse the chain to see if the value is already in the
* table. If it is there, assign to it and return.
*/
hook = bp;
while (bp != NULL && bp->telem.hashnum <= hn) {
if (bp->telem.hashnum == hn &&
equiv(&bp->telem.tref, &tended[3])) {
bp->telem.tval = tended[2];
ntended = 0;
return Success;
}
hook = bp;
bp = bp->telem.clink;
}
/*
* The value being assigned is new. Increment the table
* size, convert the table-element trapped-variable block
* to a table-element block, and link it into the chain.
*/
tp->size++;
if (hook == bp) { /* it goes at front of chain */
bp = BlkLoc(tended[1]);
bp->telem.clink = *slot;
*slot = bp;
}
else { /* it follows hook */
bp = BlkLoc(tended[1]);
bp->telem.clink = hook->telem.clink;
hook->telem.clink = bp;
}
bp->tvtbl.title = T_Telem;
bp->telem.tval = tended[2];
tended[1].dword = D_Telem;
MMShow(&tended[1], "r");
if (TooCrowded(tp)) {
tended[1].dword = D_Table;
BlkLoc(tended[1]) = (union block *)tp;
hgrow(&tended[1]);
}
ntended = 0;
return Success;
case T_Tvkywd:
ntended = 2;
putf = BlkLoc(tended[1])->tvkywd.putval;
ret_code = (*putf)(&tended[2], BlkLoc(tended[1]));
ntended = 0;
return ret_code;
default:
syserr("doasgn: illegal trapped variable");
}
ntended = 0;
return Success;
}